/*
 * Copyright 2019-2022 NXP
 * All rights reserved.
 *
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */
#include "fsl_smartdma.h"

/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.lpc_smartdma"
#endif

/*******************************************************************************
 * Definitions
 ******************************************************************************/

typedef void (*smartdma_func_t)(void);

#define SMARTDMA_BASE 0x40033000
#define SMARTDMA      ((volatile SMARTDMA_Type *)SMARTDMA_BASE)

/*******************************************************************************
 * Variables
 ******************************************************************************/
static smartdma_func_t *s_smartdmaApiTable;
static smartdma_callback_t s_smartdmaCallback;
static void *s_smartdmaCallbackParam;

const uint8_t s_smartdmaCameraFirmware[] = {
		0x21,	0x00,	0x00,	0x04,	0xE1,	0x00,	0x00,	0x04,	0xE1,	0x02,	0x00,	0x04,	0xC1,	0x03,	0x00,	0x04	,
		0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00	,
		0x12,	0x00,	0x00,	0x00,	0x12,	0x00,	0x00,	0x00,	0x12,	0x00,	0x00,	0x00,	0x12,	0x00,	0x00,	0x00	,
		0x04,	0x18,	0x04,	0x33,	0x10,	0x18,	0x68,	0x02,	0x10,	0x18,	0x60,	0x02,	0x01,	0xB0,	0x05,	0x00	,
		0x01,	0x8C,	0x05,	0x01,	0x01,	0x68,	0x07,	0x01,	0x01,	0x6C,	0x07,	0x01,	0x06,	0x74,	0x47,	0x00	,
		0x00,	0x88,	0x00,	0x00,	0x01,	0x92,	0x6C,	0xDB,	0x18,	0x64,	0x02,	0x20,	0x18,	0x64,	0x02,	0x21	,
		0x18,	0x64,	0x02,	0x22,	0x18,	0x64,	0x02,	0x23,	0x18,	0x64,	0x02,	0x24,	0x18,	0x64,	0x02,	0x25	,
		0x18,	0x64,	0x02,	0x26,	0x18,	0x64,	0x02,	0x27,	0x18,	0x64,	0x02,	0xD2,	0x00,	0x04,	0xF4,	0x0F	,
		0x1C,	0x36,	0xD0,	0x04,	0x10,	0x40,	0xE8,	0x20,	0x18,	0xEC,	0x02,	0xC2,	0x9F,	0x00,	0x00,	0x04	,
		0xBB,	0x00,	0x00,	0x04,	0x02,	0xC4,	0x08,	0x01,	0x83,	0x00,	0x00,	0x04,	0x18,	0xEC,	0x02,	0xC0	,
		0x18,	0xEC,	0x02,	0xC1,	0x18,	0xEC,	0x02,	0xC2,	0x01,	0x8C,	0x05,	0x01,	0x18,	0x20,	0x02,	0xF2	,
		0x05,	0x44,	0x00,	0x33,	0x83,	0x00,	0x00,	0x04,	0x18,	0xCC,	0x00,	0x20,	0x18,	0xCC,	0x00,	0x21	,
		0x18,	0xEC,	0x02,	0xC1,	0x18,	0xEC,	0x02,	0xC2,	0x18,	0x20,	0x02,	0xF2,	0x83,	0x00,	0x00,	0x04	,
		0x70,	0x47,	0x00,	0xBF,	0x00,	0xBF,	0x00,	0xBF,	0x00,	0xBF,	0x00,	0xBF,	0x00,	0xBF,	0x00,	0xBF	,
		0x12,	0x00,	0x00,	0x00,	0x12,	0x00,	0x00,	0x00,	0x12,	0x00,	0x00,	0x00,	0x12,	0x00,	0x00,	0x00	,
		0x04,	0x18,	0x04,	0x33,	0x10,	0x18,	0x68,	0x02,	0x10,	0x18,	0x60,	0x02,	0x01,	0xB0,	0x05,	0x00	,
		0x01,	0x8C,	0x05,	0x03,	0x01,	0x68,	0x07,	0x01,	0x01,	0x6C,	0x07,	0x01,	0x06,	0x74,	0x47,	0x00	,
		0x00,	0x88,	0x00,	0x00,	0x01,	0x92,	0x6C,	0xDB,	0x18,	0x64,	0x02,	0x20,	0x18,	0x64,	0x02,	0x21	,
		0x18,	0x64,	0x02,	0x22,	0x18,	0x64,	0x02,	0x23,	0x18,	0x64,	0x02,	0x24,	0x18,	0x64,	0x02,	0x25	,
		0x18,	0x64,	0x02,	0x26,	0x18,	0x64,	0x02,	0x27,	0x18,	0x64,	0x02,	0xD2,	0x00,	0x08,	0x14,	0x00	,
		0x00,	0x14,	0x04,	0x00,	0x1C,	0x36,	0xD0,	0x04,	0x0D,	0x80,	0xF7,	0x0F,	0x18,	0xEC,	0x02,	0xC2	,
		0x67,	0x01,	0x00,	0x04,	0x87,	0x01,	0x00,	0x04,	0x08,	0x76,	0xC7,	0x01,	0x02,	0xC4,	0x08,	0x01	,
		0x18,	0x20,	0x02,	0xF2,	0x18,	0xEC,	0x02,	0xC0,	0x00,	0x08,	0x14,	0x00,	0x00,	0x14,	0x04,	0x00	,
		0x18,	0xEC,	0x02,	0xC1,	0x18,	0xEC,	0x02,	0xC2,	0x01,	0x8C,	0x05,	0x03,	0x18,	0x20,	0x02,	0xF2	,
		0x47,	0x01,	0x00,	0x04,	0x18,	0xCC,	0x00,	0x20,	0x18,	0xCC,	0x00,	0x21,	0x00,	0x14,	0x04,	0x00	,
		0x0D,	0x88,	0xF4,	0x1F,	0x01,	0x90,	0x05,	0x02,	0x0E,	0x82,	0xF4,	0x00,	0x20,	0x04,	0x04,	0x00	,
		0x22,	0x00,	0x15,	0x00,	0x25,	0x44,	0x00,	0x33,	0x0E,	0x82,	0xE4,	0x01,	0x20,	0x04,	0x14,	0x00	,
		0x22,	0x00,	0x15,	0x00,	0x21,	0x8C,	0x05,	0x03,	0x25,	0x44,	0x00,	0x33,	0x0E,	0x82,	0xD4,	0x02	,
		0x20,	0x04,	0x24,	0x00,	0x22,	0x00,	0x15,	0x00,	0x25,	0x44,	0x00,	0x33,	0x0E,	0x82,	0xC4,	0x03	,
		0x20,	0x04,	0x34,	0x00,	0x22,	0x00,	0x15,	0x00,	0x21,	0x8C,	0x05,	0x03,	0x25,	0x44,	0x00,	0x33	,
		0x0E,	0x82,	0xB4,	0x04,	0x20,	0x04,	0x44,	0x00,	0x22,	0x00,	0x15,	0x00,	0x25,	0x44,	0x00,	0x33	,
		0x0E,	0x82,	0xA4,	0x05,	0x20,	0x04,	0x54,	0x00,	0x22,	0x00,	0x15,	0x00,	0x21,	0x8C,	0x05,	0x03	,
		0x25,	0x44,	0x00,	0x33,	0x0E,	0x82,	0x94,	0x06,	0x20,	0x04,	0x64,	0x00,	0x22,	0x00,	0x15,	0x00	,
		0x25,	0x44,	0x00,	0x33,	0x0E,	0x82,	0x84,	0x07,	0x20,	0x04,	0x74,	0x00,	0x22,	0x00,	0x15,	0x00	,
		0x21,	0x8C,	0x05,	0x03,	0x25,	0x44,	0x00,	0x33,	0x0E,	0x82,	0x74,	0x08,	0x20,	0x04,	0x84,	0x00	,
		0x22,	0x00,	0x15,	0x00,	0x25,	0x44,	0x00,	0x33,	0x0E,	0x82,	0x64,	0x09,	0x20,	0x04,	0x94,	0x00	,
		0x22,	0x00,	0x15,	0x00,	0x21,	0x8C,	0x05,	0x03,	0x25,	0x44,	0x00,	0x33,	0x0E,	0x82,	0x54,	0x0A	,
		0x20,	0x04,	0xA4,	0x00,	0x22,	0x00,	0x15,	0x00,	0x25,	0x44,	0x00,	0x33,	0x0E,	0x82,	0x44,	0x0B	,
		0x20,	0x04,	0xB4,	0x00,	0x22,	0x00,	0x15,	0x00,	0x21,	0x8C,	0x05,	0x03,	0x25,	0x44,	0x00,	0x33	,
		0x0E,	0x82,	0x34,	0x0C,	0x20,	0x04,	0xC4,	0x00,	0x22,	0x00,	0x15,	0x00,	0x25,	0x44,	0x00,	0x33	,
		0x0E,	0x82,	0x24,	0x0D,	0x20,	0x04,	0xD4,	0x00,	0x22,	0x00,	0x15,	0x00,	0x21,	0x8C,	0x05,	0x03	,
		0x25,	0x44,	0x00,	0x33,	0x0E,	0x82,	0x14,	0x0E,	0x20,	0x04,	0xE4,	0x00,	0x22,	0x00,	0x15,	0x00	,
		0x25,	0x44,	0x00,	0x33,	0x18,	0xEC,	0x02,	0xC1,	0x18,	0xEC,	0x02,	0xC2,	0x0E,	0x82,	0x04,	0x0F	,
		0x20,	0x04,	0xF4,	0x00,	0x22,	0x00,	0x15,	0x00,	0x21,	0x8C,	0x05,	0x03,	0x25,	0x44,	0x00,	0x33	,
		0x38,	0xEC,	0x02,	0x21,	0x38,	0xEC,	0x02,	0x22,	0x06,	0x88,	0x14,	0x00,	0x18,	0x20,	0x02,	0xF2	,
		0x47,	0x01,	0x00,	0x04,	0x70,	0x47,	0x00,	0xBF,	0x00,	0xBF,	0x00,	0xBF,	0x00,	0xBF,	0x00,	0xBF	,
		0x12,	0x00,	0x00,	0x00,	0x12,	0x00,	0x00,	0x00,	0x12,	0x00,	0x00,	0x00,	0x12,	0x00,	0x00,	0x00	,
		0x04,	0x18,	0x04,	0x33,	0x10,	0x18,	0x68,	0x02,	0x10,	0x18,	0x60,	0x02,	0x01,	0xB0,	0x05,	0x00	,
		0x01,	0x8C,	0x05,	0x01,	0x01,	0x68,	0x07,	0x01,	0x01,	0x6C,	0x07,	0x01,	0x06,	0x74,	0x47,	0x00	,
		0x00,	0x88,	0x00,	0x00,	0x01,	0x92,	0x6C,	0xDB,	0x18,	0x64,	0x02,	0x20,	0x18,	0x64,	0x02,	0x21	,
		0x18,	0x64,	0x02,	0x22,	0x18,	0x64,	0x02,	0x23,	0x18,	0x64,	0x02,	0x24,	0x18,	0x64,	0x02,	0x25	,
		0x18,	0x64,	0x02,	0x26,	0x18,	0x64,	0x02,	0x27,	0x18,	0x64,	0x02,	0xD2,	0x00,	0x04,	0xF4,	0x0F	,
		0x1C,	0x36,	0xD0,	0x04,	0x10,	0x40,	0xE8,	0x20,	0x18,	0xEC,	0x02,	0xC2,	0x6B,	0x03,	0x00,	0x04	,
		0x8B,	0x03,	0x00,	0x04,	0x08,	0xBE,	0x04,	0x3C,	0x82,	0xC4,	0x08,	0x01,	0x08,	0x76,	0x47,	0x02	,
		0x98,	0x20,	0x02,	0xF2,	0x06,	0x88,	0x14,	0x00,	0x18,	0xEC,	0x02,	0xC0,	0x18,	0xEC,	0x02,	0xC1	,
		0x01,	0x8C,	0x05,	0x01,	0x00,	0x08,	0x04,	0x00,	0x00,	0x10,	0x04,	0x00,	0x18,	0x20,	0x02,	0xF2	,
		0x05,	0x44,	0x00,	0x33,	0x43,	0x03,	0x00,	0x04,	0x18,	0xEC,	0x02,	0xC1,	0x06,	0x10,	0x15,	0x00	,
		0x08,	0x3E,	0x05,	0x05,	0xB8,	0xEC,	0x02,	0xC2,	0x08,	0x3E,	0x05,	0x19,	0xB8,	0xEC,	0x02,	0x22	,
		0x00,	0x08,	0x04,	0x00,	0x43,	0x03,	0x00,	0x04,	0x70,	0x47,	0x00,	0xBF,	0x00,	0xBF,	0x00,	0xBF	,
		0x00,	0xBF,	0x00,	0xBF,	0x00,	0xBF,	0x00,	0xBF,	0x00,	0xBF,	0x00,	0xBF,	0x00,	0xBF,	0x00,	0xBF	,
		0x12,	0x00,	0x00,	0x00,	0x12,	0x00,	0x00,	0x00,	0x12,	0x00,	0x00,	0x00,	0x12,	0x00,	0x00,	0x00	,
		0x04,	0x18,	0x04,	0x33,	0x10,	0x18,	0x68,	0x02,	0x10,	0x18,	0x60,	0x02,	0x01,	0xB0,	0x05,	0x00	,
		0x01,	0x8C,	0x05,	0x03,	0x01,	0x68,	0x07,	0x01,	0x01,	0x6C,	0x07,	0x01,	0x06,	0x74,	0x47,	0x00	,
		0x00,	0x88,	0x00,	0x00,	0x01,	0x92,	0x6C,	0xDB,	0x18,	0x64,	0x02,	0x20,	0x18,	0x64,	0x02,	0x21	,
		0x18,	0x64,	0x02,	0x22,	0x18,	0x64,	0x02,	0x23,	0x18,	0x64,	0x02,	0x24,	0x18,	0x64,	0x02,	0x25	,
		0x18,	0x64,	0x02,	0x26,	0x18,	0x64,	0x02,	0x27,	0x18,	0x64,	0x02,	0xD2,	0x00,	0x14,	0xF4,	0x0F	,
		0x1C,	0x36,	0xD0,	0x04,	0x10,	0x40,	0xE9,	0x20,	0x18,	0xEC,	0x02,	0xC2,	0x53,	0x04,	0x00,	0x04	,
		0x6F,	0x04,	0x00,	0x04,	0x1C,	0x36,	0xD0,	0x04,	0x10,	0x40,	0xE9,	0x20,	0x18,	0xEC,	0x02,	0xC2	,
		0x53,	0x04,	0x00,	0x04,	0x6F,	0x04,	0x00,	0x04,	0x02,	0xC4,	0x08,	0x01,	0x23,	0x04,	0x00,	0x04	,
		0x18,	0xEC,	0x02,	0xC0,	0x00,	0x08,	0x14,	0x00,	0x18,	0xEC,	0x02,	0xC1,	0x18,	0xEC,	0x02,	0xC2	,
		0x01,	0x8C,	0x05,	0x03,	0x18,	0x20,	0x02,	0xF2,	0x23,	0x04,	0x00,	0x04,	0x18,	0xCC,	0x00,	0x20	,
		0x18,	0xCC,	0x00,	0x21,	0x0D,	0x88,	0xF4,	0x1F,	0x01,	0x90,	0x05,	0x02,	0x0E,	0x82,	0xC4,	0x03	,
		0x20,	0x04,	0x04,	0x00,	0x22,	0x00,	0x15,	0x00,	0x25,	0x44,	0x00,	0x33,	0x0E,	0x82,	0x84,	0x07	,
		0x20,	0x04,	0x14,	0x00,	0x22,	0x00,	0x15,	0x00,	0x21,	0x8C,	0x05,	0x03,	0x25,	0x44,	0x00,	0x33	,
		0x0E,	0x82,	0x44,	0x0B,	0x20,	0x04,	0x24,	0x00,	0x22,	0x00,	0x15,	0x00,	0x25,	0x44,	0x00,	0x33	,
		0x18,	0xEC,	0x02,	0xC1,	0x18,	0xEC,	0x02,	0xC2,	0x0E,	0x82,	0x04,	0x0F,	0x20,	0x04,	0x34,	0x00	,
		0x22,	0x00,	0x15,	0x00,	0x21,	0x8C,	0x05,	0x03,	0x25,	0x44,	0x00,	0x33,	0x38,	0xEC,	0x02,	0x21	,
		0x38,	0xEC,	0x02,	0x22,	0x06,	0x88,	0x14,	0x00,	0x18,	0x20,	0x02,	0xF2,	0x23,	0x04,	0x00,	0x04	,
		0x70,	0x47,	0x00,	0x00													,

};

const uint32_t s_smartdmaCameraFirmwareSize = sizeof(s_smartdmaCameraFirmware);

/*******************************************************************************
 * Prototypes
 ******************************************************************************/

/*******************************************************************************
 * Codes
 ******************************************************************************/
/*!
 * brief Initialize the SMARTDMA.
 *
 * param apiMemAddr The address firmware will be copied to.
 * param firmware The firmware to use.
 * param firmwareSizeByte Size of firmware.
 */
void SMARTDMA_Init(uint32_t apiMemAddr, const void *firmware, uint32_t firmwareSizeByte)
{
    SMARTDMA_InitWithoutFirmware();
    SMARTDMA_InstallFirmware(apiMemAddr, firmware, firmwareSizeByte);
}

/*!
 * brief Initialize the SMARTDMA.
 *
 * This function is similar with SMARTDMA_Init, the difference is this function
 * does not install the firmware, the firmware could be installed using
 * SMARTDMA_InstallFirmware.
 */
void SMARTDMA_InitWithoutFirmware(void)
{
    /* Clear Smart DMA RAM */
    RESET_PeripheralReset(kSMARTDMA_RST_SHIFT_RSTn);
    CLOCK_EnableClock(kCLOCK_SmartDma);
}

/*!
 * @brief Install the firmware.
 *
 * param apiMemAddr The address firmware will be copied to.
 * param firmware The firmware to use.
 * param firmwareSizeByte Size of firmware.
 */
void SMARTDMA_InstallFirmware(uint32_t apiMemAddr, const void *firmware, uint32_t firmwareSizeByte)
{
    (void)memcpy((void *)(uint8_t *)apiMemAddr, firmware, firmwareSizeByte);
    SMARTDMA->CTRL = (0xC0DE0000U | (1U << SMARTDMA_ENABLE_GPISYNCH));
    s_smartdmaApiTable      = (smartdma_func_t *)apiMemAddr;
}

/*!
 * brief Install the complete callback function..
 *
 * param callback The callback called when smartdma program finished.
 */
void SMARTDMA_InstallCallback(smartdma_callback_t callback, void *param)
{
    s_smartdmaCallback      = callback;
    s_smartdmaCallbackParam = param;
}

/*!
 * brief Boot the SMARTDMA to run program.
 *
 * param apiIndex Index of the API to call.
 * param pParam Pointer to the parameter.
 * param mask Value set to ARM2EZH[0:1].
 */
void SMARTDMA_Boot(uint32_t apiIndex, void *pParam, uint8_t mask)
{
    SMARTDMA->ARM2EZH = (uint32_t)(uint8_t *)pParam | (uint32_t)mask;
    SMARTDMA->BOOTADR         = (uint32_t)(s_smartdmaApiTable[apiIndex]);
    SMARTDMA->CTRL = 0xC0DE0011U | (0U << SMARTDMA_MASK_RESP) | (0U << SMARTDMA_ENABLE_AHBBUF); /* BOOT */
};

/*!
 * brief Deinitialize the SMARTDMA.
 */
void SMARTDMA_Deinit(void)
{
    SMARTDMA->CTRL = 0xC0DE0000U;
    CLOCK_DisableClock(kCLOCK_SmartDma);
}

/*!
 * brief Reset the SMARTDMA.
 */
void SMARTDMA_Reset(void)
{
    RESET_PeripheralReset(kSMARTDMA_RST_SHIFT_RSTn);
    SMARTDMA->CTRL = (0xC0DE0000U | (1U << SMARTDMA_ENABLE_GPISYNCH));
}

/*!
 * brief SMARTDMA IRQ.
 */
void SMARTDMA_HandleIRQ(void)
{
    if (NULL != s_smartdmaCallback)
    {
        s_smartdmaCallback(s_smartdmaCallbackParam);
    }
}

void SMARTDMA_DriverIRQHandler(void);
void SMARTDMA_DriverIRQHandler(void)
{
    SMARTDMA_HandleIRQ();
}
